use thiserror::Error;

pub type ServiceResult<T> = Result<T, ServiceError>;

#[derive(Error, Debug)]
pub enum ServiceError {
    #[error("TMS connection error: {0}")]
    TmsConnection(String),
    
    #[error("TMS gRPC error: {0}")]
    TmsGrpc(#[from] tonic::Status),
    
    #[error("Configuration error: {0}")]
    Config(#[from] toml::de::Error),
    
    #[error("IO error: {0}")]
    Io(#[from] std::io::Error),
    
    #[error("JSON error: {0}")]
    Json(#[from] serde_json::Error),
    
    #[error("Transport error: {0}")]
    Transport(String),
    
    #[error("Tool execution error: {0}")]
    ToolExecution(String),
    
    #[error("Invalid argument: {0}")]
    InvalidArgument(String),
    
    #[error("Service unavailable: {0}")]
    ServiceUnavailable(String),
}

impl From<anyhow::Error> for ServiceError {
    fn from(error: anyhow::Error) -> Self {
        ServiceError::ServiceUnavailable(error.to_string())
    }
}

impl From<tonic::transport::Error> for ServiceError {
    fn from(error: tonic::transport::Error) -> Self {
        ServiceError::TmsConnection(error.to_string())
    }
}

impl From<rust_mcp_sdk::TransportError> for ServiceError {
    fn from(error: rust_mcp_sdk::TransportError) -> Self {
        ServiceError::Transport(error.to_string())
    }
}

impl From<rust_mcp_sdk::error::McpSdkError> for ServiceError {
    fn from(error: rust_mcp_sdk::error::McpSdkError) -> Self {
        ServiceError::ServiceUnavailable(error.to_string())
    }
}

impl From<ServiceError> for rust_mcp_sdk::schema::schema_utils::CallToolError {
    fn from(error: ServiceError) -> Self {
        rust_mcp_sdk::schema::schema_utils::CallToolError::new(error)
    }
}